package com.wfh.rpc.protocal;

import com.wfh.rpc.model.RpcRequest;
import com.wfh.rpc.model.RpcResponse;
import com.wfh.rpc.serializer.Serializer;
import com.wfh.rpc.serializer.SerializerFactory;
import io.vertx.core.buffer.Buffer;

import java.io.IOException;

/**
 * @Title: ProtocolMessageDecoder
 * @Author wangfenghuan
 * @Package com.wfh.rpc.protocal
 * @Date 2025/10/15 08:52
 * @description: 消息协议编码器
 */
public class ProtocolMessageDecoder {

    public static ProtocolMessage<?> decode(Buffer buffer) throws IOException{
        // 分别从指定的位置读出buffer
        ProtocolMessage.Header header = new ProtocolMessage.Header();
        byte magic = buffer.getByte(0);
        // 校验魔数
        if (magic != ProtocolConstant.PROTOCAL_MAGIC){
            throw new RuntimeException("消息magic非法");
        }
        header.setMagic(magic);
        header.setVersion(buffer.getByte(1));
        header.setSerializer(buffer.getByte(2));
        header.setType(buffer.getByte(3));
        header.setStatus(buffer.getByte(4));
        header.setRequestId(buffer.getByte(5));
        header.setBodyLength(buffer.getInt(13));

        // 解决半包粘包问题,只读取指定长度的数据
        byte[] bytes = buffer.getBytes(17, 17 + header.getBodyLength());
        // 解析消息体
        ProtocolMessageSerializerEnum serializerEnum = ProtocolMessageSerializerEnum.getEnumByKey(header.getSerializer());
        if (serializerEnum == null){
            throw new RuntimeException("序列化消息协议不存在");
        }
        Serializer serializer = SerializerFactory.getInstance(serializerEnum.getValue());
        ProtocolMessageTypeEnum messageTypeEnum = ProtocolMessageTypeEnum.getByKey(header.getType());
        if (messageTypeEnum == null){
            throw new RuntimeException("序列化消息类型不存在");
        }
        switch (messageTypeEnum) {
            case REQUEST:
                RpcRequest deserialize = serializer.deserialize(bytes, RpcRequest.class);
                return new ProtocolMessage<>(header, deserialize);
            case RESPONSE:
                RpcResponse rpcResponse = serializer.deserialize(bytes, RpcResponse.class);
                return new ProtocolMessage<>(header, rpcResponse);
            case HEART_BEAT:
            case OTHERS:
            default:
                throw new RuntimeException("不支持该消息类型");
        }
    }

}
